package com.example.ecommercemarketing.helper;

import com.example.ecommercemarketing.dto.MarketingElementsDTO;
import com.example.ecommercemarketing.dto.ProductDTO;
import com.example.ecommercemarketing.dto.UserDTO;
import com.example.ecommercemarketing.enums.ProductCategory;
import com.example.ecommercemarketing.service.MarketingService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Component
@Slf4j
public class MarketingHelper {
    private final MarketingService marketingService;
    private final ThreadPoolExecutor marketingThreadPool;

    @Autowired
    public MarketingHelper(
            MarketingService marketingService,
            @Qualifier("marketingThreadPool") ThreadPoolExecutor marketingThreadPool) {
        this.marketingService = marketingService;
        this.marketingThreadPool = marketingThreadPool;
    }

    /**
     * 获取所有商品大类的营销素材
     *
     * @param user 用户信息
     * @return 按商品大类分组的营销素材
     * &#064;Deprecated  此方法已废弃
     */
    @Deprecated
    public Map<String, List<MarketingElementsDTO>> getAllMarketingElementsHelpOld(UserDTO user) {
        // 模拟从数据库或推荐系统获取商品列表
        Map<String, List<MarketingElementsDTO>> result = new HashMap<>();
        for (ProductCategory category : ProductCategory.values()) {
            List<ProductDTO> products = generateProductList(category);
            result.put(category.getCode(),
                    marketingService.getMarketingElements(category, products, user));
        }
        return result;
    }

    /**
     * 并行获取所有商品大类的营销素材
     *
     * @param user 用户信息
     * @return CompletableFuture任务，用于获取按商品大类分组的营销素材
     */
    public CompletableFuture<Map<String, List<MarketingElementsDTO>>> getAllMarketingElementsFuture(UserDTO user) {
        // 1. 记录开始时间（用于监控）
        long startTime = System.currentTimeMillis();

        // 2. 创建并行任务
        List<CompletableFuture<Pair<String, List<MarketingElementsDTO>>>> futures =
                Arrays.stream(ProductCategory.values())
                        .map(category ->
                                CompletableFuture.supplyAsync(() -> processCategory(category, user), marketingThreadPool)
                                        .exceptionally(ex -> handleError(category, ex))
                        )
                        .collect(Collectors.toList());

        // 3. 合并结果
        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                .thenApply(v -> {
                    Map<String, List<MarketingElementsDTO>> result = futures.stream()
                            .map(CompletableFuture::join)
                            .filter(pair -> pair.getValue() != null) // 过滤失败的任务
                            .collect(Collectors.toMap(Pair::getKey, Pair::getValue));

                    // 记录总耗时
                    long duration = System.currentTimeMillis() - startTime;
                    log.info("营销素材获取完成，耗时{}ms，线程池状态：{}，当前线程：{}", duration, getThreadPoolStatus(), Thread.currentThread().getName());
                    return result;
                });
    }

    /**
     * 获取线程池状态（监控用）
     */
    public String getThreadPoolStatus() {
        return String.format(
                "Active: %d, Queue: %d, Completed: %d",
                marketingThreadPool.getActiveCount(),
                marketingThreadPool.getQueue().size(),
                marketingThreadPool.getCompletedTaskCount()
        );
    }

    /**
     * 异常处理（返回带错误信息的空列表）
     *
     * @param category
     * @param ex
     */
    public Pair<String, List<MarketingElementsDTO>> handleError(
            ProductCategory category, Throwable ex) {
        log.error("获取{}营销素材异常: ", category, ex);

        return Pair.of(category.getCode(), Collections.emptyList());
    }

    /**
     * 处理单个商品分类（提取方法便于异常处理）
     *
     * @param category
     * @param user
     */
    public Pair<String, List<MarketingElementsDTO>> processCategory(
            ProductCategory category, UserDTO user) {
        try {
            List<ProductDTO> products = generateProductList(category);
            return Pair.of(
                    category.getCode(),
                    marketingService.getMarketingElements(category, products, user)
            );
        } catch (Exception e) {
            throw new RuntimeException("处理分类[" + category + "]失败", e);
        }
    }

    /**
     * 模拟生成商品列表。
     * 模拟从数据库或推荐系统获取商品列表（实际项目中大致是按运营人员的配置和用户行为获取要推荐的商品列表的）
     *
     * @param category 商品大类枚举
     * @return
     */
    public List<ProductDTO> generateProductList(ProductCategory category) {
        List<ProductDTO> products = new ArrayList<>();
        Random random = new Random();

        for (int i = 0; i < 10; i++) {
            ProductDTO product = new ProductDTO();
            product.setId(1000L + i);
            product.setName(category.getName() + "商品" + (i + 1));
            product.setCategory(category);
            product.setMerchantId(2000L + i);
            product.setMerchantName("商家" + (i + 1));
            product.setSalesVolume(random.nextInt(2000));
            product.setGoodRating(0.8 + random.nextDouble() * 0.2);
            product.setMerchantScore(random.nextInt(100));
            product.setRegion(i % 2 == 0 ? "北京" : "上海");
            product.setHasOperationalConfig(i % 3 == 0);
            product.setPaidMerchant(i % 4 == 0);
            products.add(product);
        }

        return products;
    }
}
